package nc.bs.gl.eventlistener.bmcontrol;

import java.util.ArrayList;
import java.util.List;

import nc.bs.businessevent.IEventType;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.gl.hrpbctprule.constants.GlControlRuleConst;
import nc.bs.gl.hrpbctprule.util.GlControlRuleUtil;
import nc.bs.gl.pubinterface.IVoucherSave;
import nc.bs.gl.voucher.VoucherBO;
import nc.framework.commons.DaoUtils;
import nc.itf.hrpbm.budgetctrl.service.IBmBudgetControlService;
import nc.pubitf.initgroup.InitGroupQuery;
import nc.uap.ws.Bus;
import nc.ui.gl.eventprocess.VoucherEventDispatcher;
import nc.vo.arap.bx.util.BXUtil;
import nc.vo.gl.pubinterface.VoucherSaveInterfaceVO;
import nc.vo.gl.pubvoucher.OperationResultVO;
import nc.vo.gl.pubvoucher.VoucherVO;
import nc.vo.hrpbctp.busictrlscheme.BusictrlSchemeBVO;
import nc.vo.hrpbctp.busictrlscheme.BusictrlSchemeVO;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nccloud.commons.lang.StringUtils;
import org.bouncycastle.util.Arrays;


public class BmVoucherSave implements IVoucherSave {

    List<OperationResultVO> resultList = new ArrayList<OperationResultVO>();

    private VoucherVO oldVoucher = null;
    String actionCode = "SAVE";

    @Override
    public OperationResultVO[] afterSave(
            VoucherSaveInterfaceVO paramVoucher)
            throws BusinessException {
        // add by dyp1
        VoucherEventDispatcher.fireEvent(IEventType.TYPE_UPDATE_AFTER, paramVoucher.voucher);

        boolean isprojControlUsed = (BXUtil.isProductTbbInstalled("M0Z8")
                && InitGroupQuery.isEnabled(InvocationInfoProxy.getInstance().getGroupId(), "M0Z8"));
        if (!isprojControlUsed)
            return null;

        VoucherVO voucher = paramVoucher.voucher;
        //执行预算
        try {

            String year = voucher.getYear();
            String oldYear = null;
            if (oldVoucher != null)
                oldYear = oldVoucher.getYear();

//            if (oldYear != null && !year.equals(oldYear))
//                throw new BusinessException("启用预算后不允许跨年修改日期。");

            //ADD BY WW 2025-01-13 查询year和oldYear是否存在启用总账凭证预算控制的业务控制方案
            SqlBuilder sqlWhere = new SqlBuilder();
            sqlWhere.append(" billtypecode = 'C0' and isusing = 'Y'");
            sqlWhere.append(" and pk_busictrlscheme in (");
            sqlWhere.append(" select pk_busictrlscheme from hrpbctp_busictrlscheme where enablestate = 2");
            sqlWhere.append(" and nyear", new String[]{year, (StringUtils.isEmpty(oldYear) ? "9999" : oldYear)});
            sqlWhere.append(" )");

            BusictrlSchemeBVO[] qryResults = new DaoUtils().listByCondition(BusictrlSchemeBVO.class, sqlWhere.toString());
            if(!Arrays.isNullOrEmpty(qryResults)){

                if (oldYear != null && !year.equals(oldYear))
                    throw new BusinessException("启用预算后不允许跨年修改日期。");

            }
            //如果修改前凭证为暂存凭证，则将修改前凭证置空
            if(oldVoucher != null){
                if(oldVoucher.getTempsaveflag() != null && oldVoucher.getTempsaveflag().booleanValue())
                    oldVoucher = null;
            }

            //判断业务单据配置节点,是否开启了总账控制规则,如果开启,则走新逻辑,否则走旧的业务逻辑
            if (GlControlRuleUtil.enableGl(GlControlRuleConst.BILLTYPE, null)) {
                //我的新逻辑
                List<OperationResultVO> results = GlControlRuleUtil.processBudgetControl(actionCode,voucher,  oldVoucher);

                return results.toArray(new OperationResultVO[0]);

            }

            //获取预算控制VO：收入、支出进行分离
            BmCtrlVoucherVOGenerator ctrlvoGenerator = new BmCtrlVoucherVOGenerator();
            AggBmCtrlVoucherVO[] ctrlAggVos = ctrlvoGenerator.generateBmCtrlVO(voucher);
            AggBmCtrlVoucherVO[] oldCtrlAggVos = ctrlvoGenerator.generateBmCtrlVO(oldVoucher);


            /*
             * 执行预算控制
             * 先执行收入、再执行支出（支出、资本）
             */
            String topBudgetCode = null;
            AggBmCtrlVoucherVO ctrlAggVo = null;
            AggBmCtrlVoucherVO oldCtrlAggVo = null;

            /*
             * 执行收入预算
             */
//			AggBmCtrlVoucherVO ctrlAggVo_INCOME = ctrlAggVos == null ? null : ctrlAggVos[0];
//			AggBmCtrlVoucherVO oldCtrlAggVo_INCOME = oldCtrlAggVos == null ? null : oldCtrlAggVos[0];
//			topBudgetCode = "YS01";
//			//再次处理维度信息
//			ctrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, ctrlAggVo_INCOME);
//			oldCtrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, oldCtrlAggVo_INCOME);
//			if(ctrlAggVo == null && oldCtrlAggVo != null) {
//				ctrlAggVo = new AggBmCtrlVoucherVO();
//				ctrlAggVo.setParentVO(oldCtrlAggVo.getParentVO());
//			}
//			if(ctrlAggVo != null)
//				this.budgetCtrl(topBudgetCode, "收入", actionCode, voucher, ctrlAggVo, oldCtrlAggVo);	


            /*
             * 执行支出预算
             */
            AggBmCtrlVoucherVO ctrlAggVo_PAY = ctrlAggVos == null ? null : ctrlAggVos[1];
            AggBmCtrlVoucherVO oldctrlAggVo_PAY = oldCtrlAggVos == null ? null : oldCtrlAggVos[1];
            topBudgetCode = "YS02";
            //再次处理维度信息
            ctrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, ctrlAggVo_PAY);
            oldCtrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, oldctrlAggVo_PAY);
            if (ctrlAggVo == null && oldCtrlAggVo != null) {
                ctrlAggVo = new AggBmCtrlVoucherVO();
                ctrlAggVo.setParentVO(oldCtrlAggVo.getParentVO());
                ctrlAggVo.setChildrenVO(new BmCtrlVoucherDetailVO[0]);
            }
            if (ctrlAggVo != null)
                this.budgetCtrl(topBudgetCode, "支出", actionCode, voucher, ctrlAggVo, oldCtrlAggVo);

            /*
             * 执行资本预算
             */
            topBudgetCode = "YS03";
            //再次处理维度信息
            ctrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, ctrlAggVo_PAY);
            oldCtrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, oldctrlAggVo_PAY);
            if (ctrlAggVo == null && oldCtrlAggVo != null) {
                ctrlAggVo = new AggBmCtrlVoucherVO();
                ctrlAggVo.setParentVO(oldCtrlAggVo.getParentVO());
            }
            if (ctrlAggVo != null)
                this.budgetCtrl(topBudgetCode, "支出", actionCode, voucher, ctrlAggVo, oldCtrlAggVo);

            /*
             * 执行资金预算-支出
             */
            topBudgetCode = "YS05";
            //再次处理维度信息
            ctrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, ctrlAggVo_PAY);
            oldCtrlAggVo = ctrlvoGenerator.processDimValueAgain(topBudgetCode, oldctrlAggVo_PAY);
            if (ctrlAggVo == null && oldCtrlAggVo != null) {
                ctrlAggVo = new AggBmCtrlVoucherVO();
                ctrlAggVo.setParentVO(oldCtrlAggVo.getParentVO());
            }
            if (ctrlAggVo != null)
                this.budgetCtrl(topBudgetCode, "支出", actionCode, voucher, ctrlAggVo, oldCtrlAggVo);


        } catch (Exception e) {

            OperationResultVO result = BmCtrlVoucherVOGenerator.getErrorResult(voucher, e.getMessage());

            return new OperationResultVO[]{result};

        }

        return resultList.toArray(new OperationResultVO[0]);
    }

    /**
     * 预算控制
     *
     * @param topBudgetCode
     * @param otherFilter
     * @param actionCode
     * @param ctrlAggVo
     * @param oldCtrlAggVo
     * @throws BusinessException
     */
    private void budgetCtrl(String topBudgetCode, String otherFilter, String actionCode, VoucherVO voucher, AggBmCtrlVoucherVO ctrlAggVo, AggBmCtrlVoucherVO oldCtrlAggVo) throws BusinessException {

        if (ctrlAggVo != null || oldCtrlAggVo != null) {

            NCLocator.getInstance().lookup(IBmBudgetControlService.class).budgetControl(ctrlAggVo.getParentVO().getPk_group(),
                    ctrlAggVo.getParentVO().getPk_org(), "C0", null, otherFilter, actionCode, ctrlAggVo, oldCtrlAggVo, new String[]{topBudgetCode});

            OperationResultVO result = BmCtrlVoucherVOGenerator.getBmCtrlResult(ctrlAggVo, voucher);

            if (result != null)
                resultList.add(result);

        }

    }

    @Override
    public OperationResultVO[] beforeSave(
            VoucherSaveInterfaceVO paramVoucherSaveInterfaceVO)
            throws BusinessException {

        VoucherVO voucher = paramVoucherSaveInterfaceVO.voucher;
        //旧凭证
        if (voucher.getPrimaryKey() != null) {
            //查询旧凭证
            oldVoucher = new VoucherBO().queryByPk(voucher.getPrimaryKey());
            // add by dyp1
            VoucherEventDispatcher.fireEvent(IEventType.TYPE_UPDATE_BEFORE, this.oldVoucher);

        } else {
            oldVoucher = null;
        }

        return null;

    }

}
